home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap07 / SysMets / SysMets.c next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  10.7 KB  |  343 lines

  1. /*---------------------------------------------------
  2.    SYSMETS.C -- Final System Metrics Display Program 
  3.                 (c) Charles Petzold, 1998
  4.   ---------------------------------------------------*/
  5.  
  6. #define WINVER 0x0500
  7. #define _WIN32_WINNT 0x0500   // for Mouse Wheel support
  8. #include <windows.h>
  9. #include "sysmets.h"
  10.  
  11. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  12.  
  13. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  14.                     PSTR szCmdLine, int iCmdShow)
  15. {
  16.      static TCHAR szAppName[] = TEXT ("SysMets") ;
  17.      HWND         hwnd ;
  18.      MSG          msg ;
  19.      WNDCLASS     wndclass ;
  20.      
  21.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  22.      wndclass.lpfnWndProc   = WndProc ;
  23.      wndclass.cbClsExtra    = 0 ;
  24.      wndclass.cbWndExtra    = 0 ;
  25.      wndclass.hInstance     = hInstance ;
  26.      wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  27.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  28.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  29.      wndclass.lpszMenuName  = NULL ;
  30.      wndclass.lpszClassName = szAppName ;
  31.      
  32.      if (!RegisterClass (&wndclass))
  33.      {
  34.           MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
  35.                       szAppName, MB_ICONERROR) ;
  36.           return 0 ;
  37.      }
  38.      
  39.      hwnd = CreateWindow (szAppName, TEXT ("Get System Metrics"),
  40.                           WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
  41.                           CW_USEDEFAULT, CW_USEDEFAULT,
  42.                           CW_USEDEFAULT, CW_USEDEFAULT,
  43.                           NULL, NULL, hInstance, NULL) ;
  44.      
  45.      ShowWindow (hwnd, iCmdShow) ;
  46.      UpdateWindow (hwnd) ;
  47.      
  48.      while (GetMessage (&msg, NULL, 0, 0))
  49.      {
  50.           TranslateMessage (&msg) ;
  51.           DispatchMessage (&msg) ;
  52.      }
  53.      return msg.wParam ;
  54. }
  55.  
  56. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  57. {
  58.      static int  cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth ;
  59.      static int  iDeltaPerLine, iAccumDelta ;     // for mouse wheel logic
  60.      HDC         hdc ;
  61.      int         i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd ;
  62.      PAINTSTRUCT ps ;
  63.      SCROLLINFO  si ;
  64.      TCHAR       szBuffer[10] ;
  65.      TEXTMETRIC  tm ;
  66.      ULONG       ulScrollLines ;                  // for mouse wheel logic
  67.      
  68.      switch (message)
  69.      {
  70.      case WM_CREATE:
  71.           hdc = GetDC (hwnd) ;
  72.           
  73.           GetTextMetrics (hdc, &tm) ;
  74.           cxChar = tm.tmAveCharWidth ;
  75.           cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
  76.           cyChar = tm.tmHeight + tm.tmExternalLeading ;
  77.           
  78.           ReleaseDC (hwnd, hdc) ;
  79.  
  80.                // Save the width of the three columns
  81.           
  82.           iMaxWidth = 40 * cxChar + 22 * cxCaps ;
  83.  
  84.                // Fall through for mouse wheel information
  85.  
  86.      case WM_SETTINGCHANGE:
  87.           SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &ulScrollLines, 0) ;
  88.           
  89.                // ulScrollLines usually equals 3 or 0 (for no scrolling)
  90.                // WHEEL_DELTA equals 120, so iDeltaPerLine will be 40
  91.  
  92.           if (ulScrollLines)
  93.                iDeltaPerLine = WHEEL_DELTA / ulScrollLines ;
  94.           else
  95.                iDeltaPerLine = 0 ;
  96.  
  97.           return 0 ;
  98.           
  99.      case WM_SIZE:
  100.           cxClient = LOWORD (lParam) ;
  101.           cyClient = HIWORD (lParam) ;
  102.  
  103.                // Set vertical scroll bar range and page size
  104.  
  105.           si.cbSize = sizeof (si) ;
  106.           si.fMask  = SIF_RANGE | SIF_PAGE ;
  107.           si.nMin   = 0 ;
  108.           si.nMax   = NUMLINES - 1 ;
  109.           si.nPage  = cyClient / cyChar ;
  110.           SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
  111.  
  112.                // Set horizontal scroll bar range and page size
  113.  
  114.           si.cbSize = sizeof (si) ;
  115.           si.fMask  = SIF_RANGE | SIF_PAGE ;
  116.           si.nMin   = 0 ;
  117.           si.nMax   = 2 + iMaxWidth / cxChar ;
  118.           si.nPage  = cxClient / cxChar ;
  119.           SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
  120.           return 0 ;
  121.           
  122.      case WM_VSCROLL:
  123.                // Get all the vertical scroll bar information
  124.  
  125.           si.cbSize = sizeof (si) ;
  126.           si.fMask  = SIF_ALL ;
  127.           GetScrollInfo (hwnd, SB_VERT, &si) ;
  128.  
  129.                // Save the position for comparison later on
  130.  
  131.           iVertPos = si.nPos ;
  132.  
  133.           switch (LOWORD (wParam))
  134.           {
  135.           case SB_TOP:
  136.                si.nPos = si.nMin ;
  137.                break ;
  138.                
  139.           case SB_BOTTOM:
  140.                si.nPos = si.nMax ;
  141.                break ;
  142.                
  143.           case SB_LINEUP:
  144.                si.nPos -= 1 ;
  145.                break ;
  146.                
  147.           case SB_LINEDOWN:
  148.                si.nPos += 1 ;
  149.                break ;
  150.                
  151.           case SB_PAGEUP:
  152.                si.nPos -= si.nPage ;
  153.                break ;
  154.                
  155.           case SB_PAGEDOWN:
  156.                si.nPos += si.nPage ;
  157.                break ;
  158.                
  159.           case SB_THUMBTRACK:
  160.                si.nPos = si.nTrackPos ;
  161.                break ;
  162.                
  163.           default:
  164.                break ;         
  165.           }
  166.                // Set the position and then retrieve it.  Due to adjustments
  167.                //   by Windows it may not be the same as the value set.
  168.  
  169.           si.fMask = SIF_POS ;
  170.           SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
  171.           GetScrollInfo (hwnd, SB_VERT, &si) ;
  172.  
  173.                // If the position has changed, scroll the window and update it
  174.  
  175.           if (si.nPos != iVertPos)
  176.           {                    
  177.                ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos), 
  178.                                    NULL, NULL) ;
  179.                UpdateWindow (hwnd) ;
  180.           }
  181.           return 0 ;
  182.           
  183.      case WM_HSCROLL:
  184.                // Get all the vertical scroll bar information
  185.  
  186.           si.cbSize = sizeof (si) ;
  187.           si.fMask  = SIF_ALL ;
  188.  
  189.                // Save the position for comparison later on
  190.  
  191.           GetScrollInfo (hwnd, SB_HORZ, &si) ;
  192.           iHorzPos = si.nPos ;
  193.  
  194.           switch (LOWORD (wParam))
  195.           {
  196.           case SB_LINELEFT:
  197.                si.nPos -= 1 ;
  198.                break ;
  199.                
  200.           case SB_LINERIGHT:
  201.                si.nPos += 1 ;
  202.                break ;
  203.                
  204.           case SB_PAGELEFT:
  205.                si.nPos -= si.nPage ;
  206.                break ;
  207.                
  208.           case SB_PAGERIGHT:
  209.                si.nPos += si.nPage ;
  210.                break ;
  211.                
  212.           case SB_THUMBPOSITION:
  213.                si.nPos = si.nTrackPos ;
  214.                break ;
  215.                
  216.           default:
  217.                break ;
  218.           }
  219.                // Set the position and then retrieve it.  Due to adjustments
  220.                //   by Windows it may not be the same as the value set.
  221.  
  222.           si.fMask = SIF_POS ;
  223.           SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
  224.           GetScrollInfo (hwnd, SB_HORZ, &si) ;
  225.           
  226.                // If the position has changed, scroll the window 
  227.  
  228.           if (si.nPos != iHorzPos)
  229.           {
  230.                ScrollWindow (hwnd, cxChar * (iHorzPos - si.nPos), 0, 
  231.                              NULL, NULL) ;
  232.           }
  233.           return 0 ;
  234.  
  235.      case WM_KEYDOWN :
  236.           switch (wParam)
  237.           {
  238.           case VK_HOME :
  239.                SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0) ;
  240.                break ;
  241.                
  242.           case VK_END :
  243.                SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0) ;
  244.                break ;
  245.                
  246.           case VK_PRIOR :
  247.                SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0) ;
  248.                break ;
  249.                
  250.           case VK_NEXT :
  251.                SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0) ;
  252.                break ;
  253.                
  254.           case VK_UP :
  255.                SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0) ;
  256.                break ;
  257.                
  258.           case VK_DOWN :
  259.                SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0) ;
  260.                break ;
  261.                
  262.           case VK_LEFT :
  263.                SendMessage (hwnd, WM_HSCROLL, SB_PAGEUP, 0) ;
  264.                break ;
  265.                
  266.           case VK_RIGHT :
  267.                SendMessage (hwnd, WM_HSCROLL, SB_PAGEDOWN, 0) ;
  268.                break ;
  269.           }
  270.           return 0 ;
  271.  
  272.      case WM_MOUSEWHEEL:
  273.           if (iDeltaPerLine == 0)
  274.                break ;
  275.  
  276.           iAccumDelta += (short) HIWORD (wParam) ;     // 120 or -120
  277.  
  278.           while (iAccumDelta >= iDeltaPerLine)
  279.           {               
  280.                SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0) ;
  281.                iAccumDelta -= iDeltaPerLine ;
  282.           }
  283.  
  284.           while (iAccumDelta <= -iDeltaPerLine)
  285.           {
  286.                SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0) ;
  287.                iAccumDelta += iDeltaPerLine ;
  288.           }
  289.  
  290.           return 0 ;
  291.  
  292.      case WM_PAINT :
  293.           hdc = BeginPaint (hwnd, &ps) ;
  294.  
  295.                // Get vertical scroll bar position
  296.  
  297.           si.cbSize = sizeof (si) ;
  298.           si.fMask  = SIF_POS ;
  299.           GetScrollInfo (hwnd, SB_VERT, &si) ;
  300.           iVertPos = si.nPos ;
  301.  
  302.                // Get horizontal scroll bar position
  303.  
  304.           GetScrollInfo (hwnd, SB_HORZ, &si) ;
  305.           iHorzPos = si.nPos ;
  306.  
  307.                // Find painting limits
  308.  
  309.           iPaintBeg = max (0, iVertPos + ps.rcPaint.top / cyChar) ;
  310.           iPaintEnd = min (NUMLINES - 1,
  311.                            iVertPos + ps.rcPaint.bottom / cyChar) ;
  312.           
  313.           for (i = iPaintBeg ; i <= iPaintEnd ; i++)
  314.           {
  315.                x = cxChar * (1 - iHorzPos) ;
  316.                y = cyChar * (i - iVertPos) ;
  317.                
  318.                TextOut (hdc, x, y,
  319.                         sysmetrics[i].szLabel,
  320.                         lstrlen (sysmetrics[i].szLabel)) ;
  321.                
  322.                TextOut (hdc, x + 22 * cxCaps, y,
  323.                         sysmetrics[i].szDesc,
  324.                         lstrlen (sysmetrics[i].szDesc)) ;
  325.                
  326.                SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;
  327.                
  328.                TextOut (hdc, x + 22 * cxCaps + 40 * cxChar, y, szBuffer,
  329.                         wsprintf (szBuffer, TEXT ("%5d"),
  330.                              GetSystemMetrics (sysmetrics[i].iIndex))) ;
  331.                
  332.                SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
  333.           }
  334.  
  335.           EndPaint (hwnd, &ps) ;
  336.           return 0 ;
  337.           
  338.      case WM_DESTROY :
  339.           PostQuitMessage (0) ;
  340.           return 0 ;
  341.      }
  342.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  343. }